require 'flex_view/component_resolver'

module FlexView::Components
  module Core end

  class AbstractComponent
    def initialize(view, domNode)
      @domNode = domNode
      @view = view
      @children = Array.new

      processChildren
    end
    
    def compile
      return ''
    end

    private
    
    def processChildren
      if @domNode.kind_of? REXML::Element
        @domNode.each_child{ |child| treatChild(child) }
      end
    end
    
    def treatChild(domNode)
     @children.push FlexView::ComponentResolver.resolveComponent(self, domNode)
    end
    
    protected
    
    def compileChildren
      output = ''
      @children.each{ |child| output += child.compile }
      return output
    end   
  end

  class Primitive < AbstractComponent
    def compile
      out = "<#{@domNode.name}>"
      out += compileChildren
      out += "</#{@domNode.name}>"

      return out
    end
  end
  
  class TextNode < Primitive
    def compile
      return @domNode.to_s
    end
  end

  class Core::View < AbstractComponent
    def initialize(view, domNode)
      # Check root node name
      if domNode.name != 'view'
        raise FlexView::ParseException, "The initial element of each FlexView view file has to be <fxv:view>, element is [#{@domNode.name}]"
      end

      # Call parent initialize method
      super(view, domNode)
    end

    def compile
      compileChildren
    end
  end

  class Core::Out < AbstractComponent
    def compile
      # Check for child nodes (maybe later through helper/mixin?)
      if !@domNode.elements.empty?
        raise FlexView::ComponentException, 'The component [fxv:out] does not allow any child nodes.'
      end
      
      return '<%=' + @domNode.attribute(:value).value + '%>'
    end
  end
  
  class Core::If < AbstractComponent
    def compile
      # Check for expression attribute
      if !@domNode.attribute(:expression)
        raise FlexView::ComponentException, 'The component [fxv:if] requires the attribute [expression].'
      end
      
      output = '<% if ' + @domNode.attribute(:expression).value + ' %>'
      output += compileChildren
      output += '<% end %>'
      
      return output
    end
  end
end